import numpy as np
import pandas as pd
import tushare as ts
from src.facility import *

# -------------------------------------------------

ts.set_token('fe53a8928a5442e82ec2ed835f02562c7f5ac24fe7edaa2a40299c8a')
pro = ts.pro_api()


# -------------------------------------------------


class StrategyStandard:
    # 手续费
    cost_sold = 0.0013
    cost_buy = 0.0003

    # 如果传入fake_unique_id，表示处理网站上的策略
    def __init__(self, fake_unique_id=None, begin_date=None, end_date=None):
        self.owner = ''
        self.unique_id = ''
        list_fake_unique_id = fake_unique_id.split('_')
        self.unique_id = list_fake_unique_id[len(list_fake_unique_id) - 1]
        self.owner = fake_unique_id[:len(fake_unique_id) - len(self.unique_id) - 1]

        # begin_date的资金
        self.begin_date_capital = None

        # 持仓、交易、卖出、股票情况
        self.positions_lists, self.transactions_lists, self.slod_transactions_lists, self.algo_info_plot_return = \
            self.init_lists_content()

        # self.algo_info_plot_return 的衍生物
        # print(self.algo_info_plot_return)
        self.algo_name = self.algo_info_plot_return['algo_name']  # 策略名字
        self.id = self.algo_info_plot_return['id']
        self.capital_base = self.algo_info_plot_return['capital_base']  # 初始资金
        self.week_return = self.algo_info_plot_return['week_return']  # 最新的周收益
        self.week_return = self.week_return if self.week_return != -1.0 else None
        self.cum_return_plot = self.algo_info_plot_return['cum_return_plot']  # 累计收益列表
        self.first_trade_date = None  # 最早买入日期，但不是初始化日期，是初始化日期的下一个交易日。在self.init_yesterday_sum()中初始化
        self.update_time = self.algo_info_plot_return['update_time']
        self.yesterday_sum_dict = self.init_yesterday_sum()  # 昨日资产

        if begin_date is None:
            self.begin_date = self.first_trade_date
        else:
            self.begin_date = begin_date
        if end_date is None:
            self.end_date = time.strftime("%Y-%m-%d", time.localtime())
        else:
            self.end_date = end_date

        # 统计表：[买入时间、卖出时间、数量、股票代码、持仓比]
        self.pile_df = None  # 从上往下买入日期不断增大

        print('\n[策略名字=%s][策略id=%s][%s,%s,%s]' % (self.algo_name, self.id, fake_unique_id, self.owner, self.unique_id))
        # print('{}'.format(len(self.yesterday_sum_dict)))

    # 填充网站上的基本信息
    def init_lists_content(self):
        # 持仓详情
        url_positions_lists = 'https://bigquant.com/bigwebapi/algo_info/position?owner=' + \
                              self.owner + '&notebook_id=' + self.unique_id + '&limit=-1'
        # url_positions_lists = 'https://bigquant.com/bigwebapi/algo_info/position?owner=yilong_10&notebook_id
        # =1a9be36e-6de4-11ea-bc2b-0a580a830103&limit=-1'

        # 交易详情
        url_transactions_lists = 'https://bigquant.com/bigwebapi/algo_info/transaction?owner=' + \
                                 self.owner + '&notebook_id=' + self.unique_id + '&limit=-1'
        # url_transactions_lists = 'https://bigquant.com/bigwebapi/algo_info/transaction?owner=yilong_10&notebook_id
        # =1a9be36e-6de4-11ea-bc2b-0a580a830103&limit=-1'

        # 卖出详情
        url_slod_transactions_lists = 'https://bigquant.com/bigwebapi/algo_info/sold_transaction?owner=' + \
                                      self.owner + '&notebook_id=' + self.unique_id + '&limit=-1'
        # url_slod_transactions_lists = 'https://bigquant.com/bigwebapi/algo_info/sold_transaction?owner=yilong_10
        # &notebook_id=1a9be36e-6de4-11ea-bc2b-0a580a830103&limit=-1'

        # 股票情况
        url_algo_info_plot_return = 'https://bigquant.com/bigwebapi/algo_info/plot_return?owner=' + \
                                    self.owner + '&notebook_id=' + self.unique_id + '&limit=-1'
        # url_algo_info_plot_return_lists = 'https://bigquant.com/bigwebapi/algo_info/plot_return?owner=yilong_60
        # &notebook_id=da1be2d0-27dd-11eb-bbb9-0a580a800169&limit=-1'

        # print(url_positions_lists)
        # print(url_transactions_lists)
        # print(url_slod_transactions_lists)
        # print(url_algo_info_plot_return)
        # 获取json对象
        positions_lists_response_json = get_response_json(url_positions_lists)
        transactions_lists_response_json = get_response_json(
            url_transactions_lists)
        slod_transactions_lists_response_json = get_response_json(
            url_slod_transactions_lists)
        url_algo_info_plot_return_response_json = get_response_json(
            url_algo_info_plot_return)

        # 获取列表
        positions_lists = positions_lists_response_json['data']['positions_lists']
        transactions_lists = transactions_lists_response_json['data']['transactions_lists']
        slod_transactions_lists = slod_transactions_lists_response_json[
            'data']['slod_transactions_lists']
        algo_info_plot_return = url_algo_info_plot_return_response_json[
            'data']['algo_info_plot_return']

        return positions_lists, transactions_lists, slod_transactions_lists, algo_info_plot_return

    def init_yesterday_sum(self):
        d = {}
        length = len(self.cum_return_plot)
        for i in range(length):
            t_struct = time.localtime(float(int(self.cum_return_plot[i][0]) / 1000))
            t_str = time.strftime('%Y-%m-%d', t_struct)
            if i == 0:  # 策略开始运行的日子，没有昨日资产
                continue
            if i == 1:
                self.first_trade_date = t_str
            d[t_str] = self.capital_base * (1 + self.cum_return_plot[i - 1][1])  # 初始资产*昨日的累计收益
            # print('init_yesterday_sum-->', t_str, i, self.capital_base, self.cum_return_plot[i - 1][1], d[t_str])
            if i == length - 1:
                d[get_day(t_str, 1)] = self.capital_base * (1 + self.cum_return_plot[i][1])  # 最后一天，不仅有本日的昨日资产，还有明日的昨日资产
        return d

    def set_pile_df(self):
        csv_path = "csv/" + self.unique_id + ".csv"

        try:
            # print('reading csv...')
            pile_df = pd.read_csv(csv_path, encoding='utf-8')
            self.pile_df = pile_df[['买入日期', '卖出日期', '数量', '股票代码', '持仓比']]
            print('set_pile_df()-->read over-->csv_path=', csv_path)
        except FileNotFoundError:
            # print('writing csv...', self.transactions_lists)
            pile_lists = []
            # 根据交易信息填写每日交易信息pile_lists
            # 从小到大处理日期，倒着遍历交易详情
            for index in range(len(self.transactions_lists) - 1, -1, -1):  # 每个日期
                for item in self.transactions_lists[index]:  # 每个日期中包含多个交易
                    item_date = item['date']
                    item_amount_after_adjust = item['amount_after_adjust']
                    item_direction = item['direction']
                    item_sid = item['sid']
                    # 买
                    if item_direction == '买':
                        pile_object = [
                            item_date,
                            np.nan,
                            item_amount_after_adjust,
                            np.nan,
                            np.nan
                        ]
                        pile_lists.append(pile_object)
                    # 卖
                    else:
                        flag = False
                        # 就近配对，所以从大到小处理日期，倒着遍历
                        for index_2 in range(len(pile_lists) - 1, -1, -1):
                            # print(index_2, item['amount'], -pile_lists[index_2][2], pd.isna(pile_lists[index_2][1]),
                            #       pd.isna(pile_lists[index_2][3]), pile_lists[index_2][0])
                            # 防止重复，不应该直接break，可能有相同的还没安排上
                            if pd.isna(pile_lists[index_2][1]) and pd.isna(pile_lists[index_2][3]):
                                # 数量相符
                                if item_amount_after_adjust == -pile_lists[index_2][2]:
                                    pile_lists[index_2][1] = item_date
                                    pile_lists[index_2][3] = item_sid
                                    flag = True
                                    break
                        if not flag:  # 尝试总和
                            try_sum_lists = []
                            for index_3 in range(len(pile_lists) - 1, -1, -1):
                                if pd.isna(pile_lists[index_3][1]) and pd.isna(pile_lists[index_3][3]):
                                    # print('try', pile_lists[index_3][2], try_sum_number)
                                    try_sum_lists.append([index_3, pile_lists[index_3][2]])
                            try_sum_length = len(try_sum_lists)
                            for try_i in range(try_sum_length):
                                if flag:
                                    break
                                for try_j in range(try_i + 1, try_sum_length):
                                    try_sum_number = try_sum_lists[try_i][1] + try_sum_lists[try_j][1]
                                    index_first = try_sum_lists[try_j][0]
                                    index_second = try_sum_lists[try_j][0]
                                    if item_amount_after_adjust == -try_sum_number:
                                        pile_lists[index_first][1] = item_date
                                        pile_lists[index_second][3] = item_sid
                                        flag = True
                                        break
                        if not flag:
                            # print('not flag-->', pd.DataFrame(pile_lists))
                            pile_object = [
                                np.nan,
                                item_date,
                                item_amount_after_adjust,
                                item_sid,
                                np.nan
                            ]
                            pile_lists.append(pile_object)
                            print('set_pile_df()-->transaction-->居然不知道卖给谁', item_date)

                    # print('[day] %s' % (item_date,))
            print('set_pile_df()-->after transaction...-->pile_lists=', pile_lists)
            # 根据持仓信息填写每日交易信息pile_lists
            index_pile_lists = 0
            pile_lists_length = len(pile_lists)
            # 从小到大处理日期，倒着遍历持仓详情
            for index_position_lists in range(len(self.positions_lists) - 1, -1, -1):  # 每个日期
                if index_pile_lists >= pile_lists_length:  # 退出持仓
                    break
                for item in self.positions_lists[index_position_lists]:  # 每个日期中的多宗持仓
                    item_date = item['date']
                    item_hold_days = item['hold_days']
                    item_hold_percent_ratio = item['hold_percent_ratio']
                    item_value = item['value']
                    # 补救
                    print('set_pile_df()-->position-->', pile_lists[index_pile_lists][0], item_date)
                    if pd.isna(pile_lists[index_pile_lists][0]):  # 买入日期是空的，对应无头卖出，去下一行pile_list
                        index_pile_lists += 1
                        continue
                    if pile_lists[index_pile_lists][0] < item_date:  # 买入日期小于持仓日期
                        # print('[%s]中第一天的持仓信息没有被录入，尝试搜寻n+20天的持仓信息' %
                        #       (self.pile_lists[index_pile_lists][0],))
                        flag_temp = False
                        # 向后遍历持仓n天的
                        # for index_position_lists_temp in range(index_pile_lists - 1, index_pile_lists - 20, -1):
                        #     if index_position_lists_temp < 0:
                        #         break
                        #
                        #     for item2 in self.positions_lists[index_position_lists]:
                        #         # 如果卖掉了的日期都到了还没有的话，可以退出了
                        #         if item2['date'] > pile_lists[index_pile_lists][1]:
                        #             index_position_lists_temp = -1
                        #             break
                        #
                        #         if item2['first_hold_date'] == pile_lists[index_pile_lists][0] and item2['amount'] == \
                        #                 pile_lists[index_pile_lists][2]:
                        #             pile_lists[index_pile_lists][4] = item2['hold_percent_ratio']
                        #             flag_temp = True
                        #             index_position_lists_temp = -1
                        #             break

                        if flag_temp:
                            # print('补救成功！！！！！')
                            pass
                        else:
                            # print('补救失败。。。。。')
                            index_pile_lists += 1

                    if index_pile_lists >= pile_lists_length:  # 退出持仓
                        break

                    # 持有天数1的持仓信息才用做统计，持有天数大于1的我就没管
                    if item_hold_days == 1 and pile_lists[index_pile_lists][0] == item_date:
                        pile_lists[index_pile_lists][4] = item_hold_percent_ratio
                        # print(item['date'],
                        #       pd.isna(pile_lists[index_pile_lists][1]),
                        #       pd.isna(pile_lists[index_pile_lists][3]),
                        #       pd.notna(pile_lists[index_pile_lists][2])
                        #       )
                        if pd.isna(pile_lists[index_pile_lists][1]) \
                                and pd.isna(pile_lists[index_pile_lists][3]) \
                                and pd.notna(pile_lists[index_pile_lists][2]):  # 卖出没有，股票代码没有，数量有
                            # pile_lists[index_pile_lists][3] = [
                            #     item['date'],  # during_date
                            #     item['value'],  # value
                            #     pile_lists[index_pile_lists][2],  # amount
                            #     self.get_yesterday_sum(during_date=item['date'])  # yesterday_sum
                            # ]
                            print('set_pile_df()-->after position...-->pile_lists=', pile_lists)
                            if len(pile_lists) == 0:
                                self.pile_df = None
                                return
                            self.pile_df = pd.DataFrame(pile_lists)
                            self.pile_df.columns = ['买入日期', '卖出日期', '数量', '股票代码', '持仓比']
                            self.pile_df.to_csv(csv_path)
                            print('set_pile_df()-->write over-->csv_path=', csv_path)
                            print('set_pile_df-->get_code_only()-->item_date=', item_date)
                            pile_lists[index_pile_lists][3] = self.get_code_only(
                                during_date=item_date,
                                value=item_value,
                                amount=pile_lists[index_pile_lists][2]
                            )
                        index_pile_lists += 1

                    # print('[day] %s' % (item['date'],))
                    if index_pile_lists >= pile_lists_length:  # 退出持仓
                        break

            print('set_pile_df()-->after position...-->pile_lists=', pile_lists)
            if len(pile_lists) == 0:
                self.pile_df = None
                return
            self.pile_df = pd.DataFrame(pile_lists)
            self.pile_df.columns = ['买入日期', '卖出日期', '数量', '股票代码', '持仓比']
            self.pile_df.to_csv(csv_path)
            print('set_pile_df()-->write over-->csv_path=', csv_path)

    def get_code_only(self, during_date, value, amount):
        # print('[during_date = %s]' % (during_date,))

        closing_price = value / amount
        yesterday_sum = self.yesterday_sum_dict.get(during_date)
        today_sum = self.yesterday_sum_dict.get(get_day(during_date, 1))

        today_return = 0
        if today_sum is not None:
            today_return = today_sum / yesterday_sum - 1
        else:
            today_return = self.algo_info_plot_return['today_return']  # 这是对应最新一日的情况中只有买入的情况
        print('get_code_only()-->[during_date][yesterday_sum][today_sum][today_return]',
              during_date, yesterday_sum, today_sum, today_return)

        today_return_sold = self.get_df_result_1(begin_date=during_date, end_date=during_date,
                                                 original_capital=self.yesterday_sum_dict.get(during_date),
                                                 select_flag='sold')
        today_return_hold = self.get_df_result_1(begin_date=during_date, end_date=during_date,
                                                 original_capital=self.yesterday_sum_dict.get(during_date),
                                                 select_flag='hold')
        today_return_buy = today_return - today_return_sold - today_return_hold
        print('[today_return][today_return_sold][today_return_hold][today_return_buy]', today_return, today_return_sold,
              today_return_hold, today_return_buy)

        open_price = (amount * closing_price - today_return_buy * yesterday_sum) / amount / (
                1 + StrategyStandard.cost_buy)
        print('[closing_price = %s][open_price = %s]' % (closing_price, open_price))

        csv_path_2 = "csv/" + during_date + ".csv"
        df_stock = None
        print(csv_path_2)
        try:
            # print('reading csv...')
            df_stock = pd.read_csv(csv_path_2, encoding='utf-8')
            # print('reading over...')
        except FileNotFoundError:
            df_stock = pro.daily(trade_date=during_date.replace('-', ''))
            df_stock = df_stock[['ts_code', 'close', 'open']]
            df_stock = df_stock.sort_values(by=['close', 'open'])
            df_stock.to_csv(csv_path_2)

        diff = 0.005
        # 只根据收盘价查找
        df_one_stock = df_stock[(abs(df_stock['close'] - closing_price) < 0.005)]
        df_one_stock.index = [i for i in range(df_one_stock.index.size)]
        if df_one_stock is not None and df_one_stock.index.size == 1:
            sid = df_one_stock.at[0, 'ts_code']
            print('get_code_only()-->according to close...'
                  '[during_date=%s][sid=%s][closing_price=%3f][value=%3f][amount=%3f]'
                  % (during_date, sid, closing_price, value, amount))
            return sid

        code_lists = []  # 根据收盘价和开盘价一起查找
        # 因为tushare的数据有时候很粗糙（比如1.2写成1，从而有0.1的误差），所以设定逐次增加。
        while len(code_lists) == 0 and diff < 0.5:
            a, b = None, None
            a = df_stock[
                (abs(df_stock['close'] - closing_price) < diff) &
                (abs(df_stock['open'] - open_price) < diff)
                ]
            b = np.array(a['ts_code'])
            code_lists = list(b)
            diff += 0.01
        if len(code_lists) == 0:
            print('get_code_only()-->Not Found ts_code.....[during_date=%s][closing_price=%3f]'
                  '[open_price=%3f][value=%3f][amount=%3f]'
                  % (during_date, closing_price, open_price, value, amount))
            # raise Exception('Not Found ts_code.....')
        else:
            sid = code_lists[0]
            print('get_code_only()-->according close and open...[during_date=%s][sid=%s][closing_price=%3f]'
                  '[open_price=%3f][value=%3f][amount=%3f]'
                  % (during_date, sid, closing_price, open_price, value, amount))
            return sid

    def get_HZ300_result(self):

        csv_path = 'csv/399300SZ.csv'
        try:
            df_stock = pd.read_csv(csv_path, encoding='utf-8')
            # print('reading csv...')
        except FileNotFoundError:
            # print('writing csv...')
            df_stock = pro.index_daily(ts_code='399300.SZ')
            df_stock.to_csv(csv_path)
        df_stock = df_stock[['trade_date', 'close', 'open', 'pre_close']]  # 既是处理read后的空列，也是这样加快检索
        # print(df_stock)

        original_capital = self.yesterday_sum_dict.get(self.begin_date)
        if original_capital is None:
            print('这天没有交易，手动设定一下begin_date为交易日子')
        diff_capital = 0
        # 采用公式2计算：数据经过验证，HZ300的收益率都是依据持有的，不算买入卖出.

        # df_stock从上到下日期递减，我们要日期递增，所以倒着
        j = df_stock.index.size - 1
        amount = None
        for k in range(j, -1, -1):
            if get_translated_trade_date(df_stock.at[k, 'trade_date']) >= self.begin_date:
                diff_capital += -original_capital  # 全部持有
                amount = original_capital / df_stock.at[k, 'close']
                # print(k, get_translated_trade_date(df_stock.at[k, 'trade_date']), self.begin_date,
                #       df_stock.at[k, 'close'], amount, diff_capital)
                break
        for k in range(j - 1, -1, -1):
            if get_translated_trade_date(df_stock.at[k, 'trade_date']) >= self.end_date:
                diff_capital += df_stock.at[k, 'close'] * amount
                # print(k, get_translated_trade_date(df_stock.at[k, 'trade_date']), self.end_date,
                #       df_stock.at[k, 'close'], amount, diff_capital)
                break
        result = diff_capital / original_capital
        return result

    # 今日收盘、今日开盘
    def buy_amount(yesterday_sum, amount, today_close, today_open):
        # print(yesterday_sum, amount, today_close, today_open)
        today_sum = yesterday_sum + today_close * amount - today_open * amount - today_open * amount * StrategyStandard.cost_buy
        result = (today_sum - yesterday_sum) / yesterday_sum
        return result, today_sum

    # 今日收盘、昨日收盘
    def hold_amount(yesterday_sum, amount, today_close, yesterday_close):
        today_sum = yesterday_sum + today_close * amount - yesterday_close * amount
        result = (today_sum - yesterday_sum) / yesterday_sum
        return result, today_sum

    # sold_price is 今日收盘（收盘卖） or 今日开盘（开盘卖），昨日收盘
    def sold_amount(yesterday_sum, amount, sold_price, yesterday_close):
        today_sum = yesterday_sum + sold_price * amount - sold_price * amount * StrategyStandard.cost_sold - yesterday_close * amount
        result = (today_sum - yesterday_sum) / yesterday_sum
        return result, today_sum

    # 这里采用总资产计算公式1
    # 指定begin_date和 end_date
    def get_df_result_1(self, begin_date=None, end_date=None, select_flag=None, original_capital=None):
        begin_date = begin_date
        end_date = end_date
        original_capital = original_capital

        # 没有自定义就使用默认构造的
        if begin_date is None:
            begin_date = self.begin_date
        if end_date is None:
            end_date = self.end_date
        if original_capital is None:
            original_capital = self.yesterday_sum_dict.get(begin_date)
        print('get_df_result_1-->', begin_date, end_date, original_capital)
        if original_capital is None:  # 如果还是None，说明出现了错误的买入
            return None

        cum_capital = original_capital

        # print('self.get_df_result_1()-->', self.pile_df)
        # self.pile_df按从0开始，日期递增
        for i in range(self.pile_df.index.size):
            buy_date = self.pile_df.at[i, '买入日期']
            sold_date = self.pile_df.at[i, '卖出日期']
            sid = self.pile_df.at[i, '股票代码']
            # print('sid = [%s]' % (sid,))
            if pd.isna(sid):  # 这行没有股票代码（说明买入计算股票没有算出来）那么就什么都不计算
                continue
            sid = sid[:6] + ('.SZ' if sid[0] < '6' else '.SH')
            # print('sid = [%s]' % (sid,))
            amount = self.pile_df.at[i, '数量']

            # 买入日期超过结束日期退出，自然卖出日期更超过，而且之后的记录是越来越大
            if pd.notna(buy_date) and buy_date > end_date:  # buy_date有NAN，是由于set_pile_df()中的无头卖出
                # print('超过今天才退出', buy_date, end_date)
                break

            # 卖出日期小于起始日期不处理，自然买入日期更小于
            if pd.notna(sold_date) and sold_date < begin_date:  # sold_date 有NAN，是由于set_pile_df()中的无尾买入
                # print('小于买入日期不处理', sold_date, begin_date)
                continue

            df_stock = None  # df_stock是从0开始日期递减
            csv_path = 'csv/' + sid + '.csv'
            # print(csv_path)
            try:
                df_stock = pd.read_csv(csv_path, encoding='utf-8')
            except FileNotFoundError:
                df_stock = pro.daily(ts_code=sid)
                df_stock.to_csv(csv_path)
            df_stock = df_stock[['trade_date', 'close', 'open', 'pre_close']]  # 既是处理read后的空列，也是这样加快检索

            # 从小的日子开始，所以倒着df_stock，处理买入的情况
            j = df_stock.index.size - 1
            if pd.notna(buy_date):
                for k in range(j, -1, -1):
                    trade_date = df_stock.at[k, 'trade_date']
                    trade_date = get_translated_trade_date(trade_date)
                    # print('?', k, trade_date, self.pile_df.at[i, '买入日期'])

                    # 处理停市的买的日子
                    if trade_date == buy_date:  # 有交易情况
                        j = k
                        if buy_date < begin_date:  # 买入日期小于起始不处理买入，然后去看是否处理持仓和卖出
                            break
                        if select_flag is None or select_flag == 'buy':
                            today_close = df_stock.at[k, 'close']
                            today_open = df_stock.at[k, 'open']
                            cum_capital = StrategyStandard.buy_amount(yesterday_sum=cum_capital,
                                                                      amount=amount,
                                                                      today_close=today_close,
                                                                      today_open=today_open)[1]
                            print('买', k, trade_date, amount, '收', today_close, '开', today_open, cum_capital)
                        break

            # 处理持仓和卖出
            if pd.notna(sold_date):
                for k in range(j - 1, -1, -1):  # j-1自然因为买入卖出不可能在同一天
                    trade_date = df_stock.at[k, 'trade_date']
                    trade_date = get_translated_trade_date(trade_date)

                    # 交易日期小于起始日期，就去下一个交易日
                    if trade_date < begin_date:
                        continue
                    # 交易日期超过结束日期，就不处理持仓和卖了
                    if trade_date > end_date:
                        break

                    # 处理停市的卖的日子：
                    if trade_date == sold_date:
                        if select_flag is None or select_flag == 'sold':
                            sold_price = df_stock.at[k, 'close']
                            yesterday_close = df_stock.at[k, 'pre_close']
                            cum_capital = StrategyStandard.sold_amount(yesterday_sum=cum_capital,
                                                                       amount=amount,
                                                                       sold_price=sold_price,
                                                                       yesterday_close=yesterday_close)[1]
                            print('卖', k, trade_date, amount, '今收', sold_price, '昨收', yesterday_close, cum_capital)
                        break

                    # 处理持仓
                    if select_flag is None or select_flag == 'hold':
                        today_close = df_stock.at[k, 'close']
                        yesterday_close = df_stock.at[k, 'pre_close']
                        cum_capital = StrategyStandard.hold_amount(yesterday_sum=cum_capital,
                                                                   amount=amount,
                                                                   today_close=today_close,
                                                                   yesterday_close=yesterday_close)[1]
                        print('持', k, trade_date, amount, '今收', today_close, '昨收', yesterday_close, cum_capital)

            # print('\r [%d]/[%d]...' % (i, self.pile_df.index.size), end=' ')
        # print('')
        result = (cum_capital - original_capital) / original_capital
        return result


# -------------------------------------------------

# 策略的排名
def get_share_algo_lists(owner):
    # 查寻作者id
    url_share_algo_lists = 'https://bigquant.com/bigwebapi/algo_list/share?page=1&limit=-1'
    # url_share_algo_lists = 'https://bigquant.com/bigwebapi/algo_list/share?page=1&limit=10&order_by=-grade&search=' + \
    #                        owner
    # url_share_algo_lists = 'https://bigquant.com/bigwebapi/algo_list/share?page=1&limit=10&order_by=-grade&search
    # =yilong_10' print(url_share_algo_lists)

    response_json = get_response_json(url_share_algo_lists)

    share_algo_lists = response_json['data']['share_algo_lists']

    return share_algo_lists


# 按照正式的策略
def back_test_example_standard(fake_unique_id, end_date):
    fake_unique_id = fake_unique_id
    begin_date = get_day(end_date, 0)  # 某天的总收益率
    # begin_date = get_day(end_date, -6)  # 一周的累计收益率
    my_strategy = StrategyStandard(fake_unique_id=fake_unique_id, begin_date=begin_date, end_date=end_date)
    # my_strategy = Strategy(fake_unique_id=unique_id, end_date=end_date)
    # algo_name = my_strategy.algo_name
    # print(algo_name)
    # print(my_strategy.yesterday_sum_dict.get('2020-07-31'))
    my_strategy.set_pile_df()
    # result_week_return = my_strategy.get_df_result_1()
    # if result_week_return is None:  # 说明买入错误，一般是策略已经是死策略停产了
    #     print('week_return is None.')
    #     return
    # else:
    #     return result_week_return
    # result_300 = my_strategy.get_HZ300_result()
    # print(result_week_return, result_300)


def print_can_pass_criteria(end_date, result_300=None):
    # owner_lists = ['yilong_10', 'yilong_20', 'yilong_30', 'yilong_40', 'yilong_50', 'yilong_60']
    end_date = end_date
    # begin_date = get_day(end_date, -6)
    begin_date = '2021-01-25'
    strategy_lists = []
    # for i, owner in enumerate(owner_lists):
    if True:
        # print('----------------------------%s----------------------------' % (owner,))
        share_algo_lists = get_share_algo_lists(None)
        share_algo_lists_length = len(share_algo_lists)
        for j, share_algo in enumerate(share_algo_lists):
            print('----------------------------%d/%d----------------------------' % (j, share_algo_lists_length))
            my_strategy = StrategyStandard(share_algo['unique_id'], begin_date=begin_date, end_date=end_date)
            # 胜率
            win_ratio = my_strategy.algo_info_plot_return['win_ratio'] if my_strategy.algo_info_plot_return[
                                                                              'win_ratio'] != '' else 0
            # 最大回撤
            max_drawdown = my_strategy.algo_info_plot_return['max_drawdown'] if my_strategy.algo_info_plot_return[
                                                                                    'max_drawdown'] != '' else 1
            # 夏普率
            sharpe = my_strategy.algo_info_plot_return['sharpe'] if my_strategy.algo_info_plot_return[
                                                                        'sharpe'] != '' else 0
            # 运行天数
            day_num = len(my_strategy.cum_return_plot)
            # print(win_ratio, max_drawdown, sharpe, day_num, my_strategy.first_trade_date, end_date)
            # 排除
            if win_ratio <= 0.5:
                continue
            if max_drawdown >= 0.2:
                continue
            if sharpe <= 2:
                continue
            if day_num <= 5:
                continue
            # print(my_strategy.first_trade_date, begin_date, end_date)
            if my_strategy.first_trade_date > end_date:  # 股票还没有开始
                continue
            if my_strategy.update_time < '2021-01-01':  # 死股票
                continue
            # print(my_strategy.first_trade_date,begin_date)
            if my_strategy.first_trade_date > begin_date:  # 在begin_date有空档，说明新生策略
                print('print_can_pass_criteria()-->set_pile_df()-->A')
                my_strategy.begin_date = my_strategy.first_trade_date  # 调整正确的起始日期begin_date
                my_strategy.set_pile_df()
                result_week_return = my_strategy.get_df_result_1()
                if result_week_return is None:
                    continue
                if result_300 is None:
                    result_300 = my_strategy.get_HZ300_result()
            else:  # 老策略
                print('print_can_pass_criteria()-->set_pile_df()-->B')
                result_week_return = my_strategy.week_return
                if result_week_return is None:  # 说明新生策略
                    continue
                if result_300 is None:
                    result_300 = my_strategy.get_HZ300_result()
                if result_week_return > result_300:
                    my_strategy.set_pile_df()
            print('[result_week_return][result_300]', result_week_return, result_300)
            if result_week_return <= result_300:
                continue
            strategy_lists.append([
                my_strategy.unique_id, my_strategy.id, my_strategy.owner, my_strategy.algo_name,
                win_ratio, max_drawdown, sharpe, day_num,
                result_week_return, result_300,
                np.nan, np.nan, np.nan, np.nan
            ])
            # ['unique_id', 'id','策略作者', '策略名字', '胜率','最大回撤','夏普率','运行交易日','最近1周收益率','300基准收益率','持有一天的累计一周收益',
            # '持有两天的累计一周收益','持有一天的累计一月收益','持有两天的累计一月收益']
    print(strategy_lists)
    csv_path_strategy_lists = 'csv/pool' + '.csv'
    df_strategy_lists = pd.DataFrame(strategy_lists)
    df_strategy_lists.columns = ['unique_id', 'id', '策略作者', '策略名字',
                                 '胜率', '最大回撤', '夏普率', '运行交易日',
                                 '最近1周收益率', '300基准收益率',
                                 '持有一天的累计一周收益', '持有两天的累计一周收益', '持有一天的累计一月收益', '持有两天的累计一月收益'
                                 ]
    df_strategy_lists.to_csv(csv_path_strategy_lists)
    print('--------%s---------' % (csv_path_strategy_lists,))


def main():
    end_date = '2021-02-02'

    # fake_unique_id = '作者名' + '_' + 'unique_id'
    # fake_unique_id = 'pk02_59282b86-f4fa-11ea-98fe-0a580a8000ab'
    # back_test_example_standard(fake_unique_id=fake_unique_id, end_date=end_date)

    fake_unique_id_list = [
        'yilong_30_c1b98d00-5708-11eb-bb2f-0a580a8000ca',
        'yilong10_fc2f227e-44ed-11eb-9e3f-0a580a83010c',
        'zx18111624912_9084294c-41ab-11eb-9df2-0a580a83010c'
    ]
    for _ in fake_unique_id_list:
        back_test_example_standard(fake_unique_id=_, end_date=end_date)

    # print_can_pass_criteria(end_date=end_date, result_300=-1.0)
    # print_can_pass_criteria(end_date=end_date)


if __name__ == '__main__':
    main()
